给 Codex 装上无限画布,AI 改图终于不用翻对话记录了

404 字

林月半子聊AI 林月半子的AI笔记 2026年6月23日 07:30

关注 「 林月半子的AI笔记 」,设为「 星标

我是林月半子,教你用AI干掉90%的重复劳动

大家好,我是开始学习 Codex 的林月半子。

现在用 AI 做图已经很方便了,相信很多人都在用。我自己也封装了生图 Skill,在 Codex 里一句话就能出一张封面图。

但你有没有遇到过这种情况。AI 出的图不是一步到位的,v1 改文案位置、v2 换衣服、v3 调眼镜……改到第五版的时候,回头一看对话记录,已经完全找不到哪个版本是哪条消息生成的了。

图片

更头疼的是,有时候一个版本经过了好几轮对话才满意,中间的决策过程在对话里是线性的,根本没法回溯。你只记得"那个版本挺好的",但找不到了。

直到端午节的时候,在 X 上刷到一条视频。钟二信(@zhongerxin)发了一个 Codex + 无限画布的演示,在画布上直接标注、直接改图,整个流程一气呵成。

我当时看完的第一反应就是:这不就是我一直想要的东西吗?

然后我向 AI 提了需求,AI 把这个思路复刻了出来。现在基本已经摆脱"在对话记录里翻版本"的烦恼了。

先放一个我复刻完之后实际跑的效果:

Prompt Canvas:我的思路

我做的这个工具叫 Prompt Canvas,以 Codex 插件的形式跑在本地,装好之后在插件目录的 Personal 标签下就能看到。

Image

画布数据全部存在本地(SQLite + 文件系统),不用担心隐私问题。

核心逻辑是这样的:

第一层:版本管理。

每张生成的图片都有版本号。v1、v2、v3,直接在画布上并排展示。你能一眼看到从初稿到终稿的迭代过程,不用翻文件夹。

图片

第二层:本地持久化。

用 SQLite 存所有数据。画布状态、图片版本、批注记录,全部落盘。关掉 Codex 再打开,上次的工作还在。不是那种浏览器里一刷新就没了的临时玩具。

第三层:批注工作流。

这是核心。画布上方有一排按钮:「批注」「备注」「复制批注指令」「提交给 Codex」。你在图上画圈、写文字,然后点一下「提交给 Codex」,系统会把你的批注变成一条结构化指令,直接发给 Codex 执行。

图片

为什么"批注变指令"这个设计这么重要? 因为传统的做法是截图丢给 AI,AI 要先做图像识别——"哦,用户在右下角画了个圈,圈住的是人物的衣服"——这个识别过程本身就不靠谱。 但如果你直接告诉它"位置:右下角,覆盖面积 6.4%,指令:换成红色时尚一些的衣服",它就不需要猜了。 精确的输入,才能有精确的输出。

具体跑一遍是这样的:

Step 1:选择插件,打开画布

先在 Codex 里选择 Prompt Canvas 插件,告诉它"打开一个新的画布"。Codex 会自动启动本地画布服务,浏览器里打开画布界面。

图片

后续的操作跟你平时用 Codex 画图一样。告诉它你要一张什么样的封面图、定好尺寸,插件会自动在画布上建一个 21:9 的 AI Image Holder,然后跑生图。

这里要说一下,我是没有订阅 GPT 的,所以 Codex 里没有 GPT Image 可以用。生图走的是我以前自己写的 Skill:linyuebanzi-image-gen,底层调的外部 API。

这也是为什么我需要一个画布来管理这个流程。钟二信用 Cowart 的时候,生图能力直接走 GPT Image 2,订阅用户基本可以自由干。但我这边得靠自己的 Skill 串起来,画布就成了那个把"生图 Skill + 批注 + 版本管理"粘在一起的胶水层。

生成完毕,v1 就出现在画布上了。

图片

Step 2:迭代修改——两种方式

v1 出来之后,怎么改?我做了两种方式,一简一精,适合不同场景。

方式一:截图丢给 Codex(最快)

最简单粗暴的方式。

直接点画布右上角的截图按钮,把当前画面截下来丢给 Codex,然后用自然语言告诉它哪里要改,甚至不需要说,直接丢图。

这个方式适合改动比较明确的场景。比如你生了一张时尚穿搭图,想把蓝色毛衣换个颜色、短裙改成长裙。直接截图丢给 Codex,用自然语言告诉它"换毛衣颜色"、"把短裙加长",Codex 看截图就能理解你的意思,直接出 v2。

,时长00:24

方式二:批注后提交给 Codex(最精确)

这是核心玩法,也是整个工具最有意思的设计。

,时长00:20

操作上很简单:点「批注」按钮进入批注模式,在图上画箭头、画圈、写文字。比如 AI 生了一张拉面的图,你觉得料不够丰富,直接在碗上方画个箭头写"再加几片牛肉"。标完之后,点画布上方的「提交给 Codex」按钮,这会把你画的批注写成一份修改说明书,存到项目目录的 canvas/pages/\/_pending/ 文件夹里。

然后你需要在 Codex 对话框里说一句"我已提交变更",Codex 收到这句话后,会通过 MCP 工具 prompt_canvas_get_pending_submits 去 _pending/ 文件夹里读取这份说明书。

图片

但背后发生的事情挺值得说说的。

这其实是一个"本地文件驱动"的异步协作设计,三个角色各干各的:

图片

1、用户在画布上做了什么?

你在画布上画批注(箭头、画笔圈、文字),本质上是在一张图片上留下空间化的修改指令。

比如:

  • 在碗的上方画个箭头,写"再加几片牛肉"
  • 在汤面区域画个圈,写"汤色再浓一点"

这些批注会被 buildSubmitPayload() 函数收集起来,转换成结构化的数据:

{
  "canvas_id":"...",
  "target":{
    "shape_id":"ai_xxx",
    "version":"v1",
    "image_url":"/page-assets/xxx/ramen-v1.png",
    "prompt":"..."
  },
  "annotations":[
    {"kind":"draw","region":"上方","text":"再加几片牛肉"},
    {"kind":"arrow","region":"中部","text":"汤色再浓一点"}
  ],
  "next_version":"v2",
  "md":"...人类可读的 markdown..."
}

看这个 JSON 结构,你画的每一笔批注都变成了 annotations 数组里的一条记录。什么类型(画笔圈/箭头/文字)、在图片的什么区域、写了什么修改意见,全部结构化了。

其中最关键的是 md 字段。一段用 markdown 写好的、带空间位置信息的修改说明书。

2、点击"提交给 Codex"时发生了什么?

前端做了三件事:

1)生成 markdown 修改说明书。 把批注整理成这样的文本:
目标版本:v1 (ramen-v2)
目标图:/page-assets/xxx/ramen-v1.png
目标尺寸:1680×720

视觉批注 (2):
1. [箭头] 位于 上方:"再加几片牛肉" 
2. [画笔圈] 覆盖约 5.2% 区域,位于 中部:"汤色再浓一点"
...

请生成 v2:
- 基于 v1
- 保持 v1 的构图与尺寸 (1680×720)
- 调用 linyuebanzi-image-gen,生成后 fill_ai_image_holder 到本画布
2)复制到剪贴板。

兜底方案,即使 Codex 轮询没赶上,你也能直接粘贴给 Codex。

3)调用 /api/submit 写入 pending 文件。

本地服务收到请求后,把修改说明书存成带时间戳的.md 和.json 两个文件,放到项目目录的 _pending/ 文件夹里。.md 给 Codex 看(人类也能看),.json 给后续自动化流程用。

这一步相当于把用户的"修改请求"投递到一个本地邮箱里。实际的文件结构长这样:

_pending/
├── _done/                              ← 已处理的归档
│   ├── submit-20260622T071330.json
│   └── submit-20260622T071330.md
├── submit-20260622T075222.json         ← 待处理(结构化数据)
└── submit-20260622T075222.md           ← 待处理(人类可读说明书)

_done/ 里的是 Codex 已经处理完的,外面的是还在排队等处理的。一眼就能看出哪些改了、哪些没改。

3、Codex 怎么知道有新任务?

Codex 不会被动接收通知,而是通过 MCP 暴露的 prompt_canvas_get_pending_submits 工具主动轮询。拿到 pending 列表后,读取 markdown 内容,理解你要改什么,然后:

  1. 1.生成 v2 图片
  2. 2.调用 prompt_canvas_fill_ai_image_holder 把新图放到画布上
  3. 3.调用 prompt_canvas_mark_submit_done 把这个 pending 请求标记为已处理

处理完的文件会从 _pending/ 移到 _pending/_done/,不会重复执行。

为什么这样设计?

核心是异步解耦。你提交修改请求的时候,Codex 不一定在线、不一定在监听。把请求写成文件,Codex 随时来取,相当于一个本地消息队列。而且每个提交都有时间戳文件,什么时候提的、改了什么、Codex 处理了没有,全部可回溯。即使 Codex 轮询没赶上,markdown 也已经复制到了剪贴板,用户可以直接粘贴给 Codex,双重保险。

这个 pending 提交机制是 Prompt Canvas 特有的设计。相比之下,Cowart 的交互方式是截图直接让 Codex 生图。更直觉,但批注信息是视觉的、模糊的。而 Prompt Canvas 把批注整理成结构化的 markdown + json,存到本地文件系统,Codex 通过 MCP 工具读取处理。一个走的是"截图让 AI 看",一个走的是"结构化指令让 AI 读"。

一句话总结:"提交给 Codex" = 把画布上的批注转换成一份带空间位置的 markdown 修改说明书,存到本地的 _pending/ 文件夹里,Codex 通过 MCP 工具轮询这个文件夹,拿到需求后生成新图并回填到画布。

图片

两种方式不是互斥的,一次迭代里你可能混着用。先截图让 Codex 看看整体感觉,再用批注精确标注细节。

开源了,你也可以直接用

我已经把 Prompt Canvas 开源了:github.com/lqshow/prompt-canvas

顺带一提,给我灵感的钟二信也把他的项目 Cowart 开源了。两个项目的思路不太一样,Cowart 更偏通用创意画布,像 Figma-lite;我的更偏生产管线,核心在版本管理和结构化批注指令。如果你订阅了 GPT 想要一个自由发挥的画布,可以试试 Cowart;如果你像我一样需要一条高效的图片迭代流水线,试试 Prompt Canvas。

下面说说怎么装。

1、添加 Marketplace

在终端里执行:

codex plugin marketplace add lqshow/prompt-canvas

2、安装生图 Skill(依赖)

Prompt Canvas 的生图能力依赖我的 linyuebanzi-image-gen Skill,需要一起装:

npx skills add lqshow/linyuebanzi-skills -g

3、安装并启用插件

打开 Codex,点左侧的「插件」面板,在 marketplace 选择器里切到 Personal,找到 Prompt Canvas,点击「安装插件」。

图片

4、打开画布开始用

装好后,在 Codex 里选择这个插件,直接说"打开一个新的画布",Codex 会自动检查环境、启动画布服务、注册 MCP,一切就绪后画布就开在浏览器里了。

图片

接下来就是前面讲的那套流程。告诉 Codex 你要什么图,插件自动生成 v1,然后批注、提交、迭代。

最后

感谢钟二信。

说实话,画布这个东西一点都不难,开源的无限画布方案一搜一大把,技术门槛真不高。但"Codex + 画布"这个组合,我之前是真没往这个方向想过。看到 Cowart 的那一刻,我才意识到这条路是通的。

技术不难,难的是思路要打开。

很多时候你不是缺能力,是缺那个"哦,原来还能这么玩"的瞬间。钟二信的 Cowart 给了我这个瞬间,所以这篇文章也算是一个回馈,把我在这个方向上多走的那几步分享出来。

如果觉得不错,随手点个「赞」和「在看」,转发给需要的朋友吧~ 第一时间收到推送,记得给我个星标⭐

林月半子的AI笔记

邀请你前往腾讯公益一起捐

给困境儿童送关爱包

61人捐赠